return ret;
}
+gboolean
+ostree_mutable_tree_ensure_parent_dirs (OstreeMutableTree *self,
+ GPtrArray *split_path,
+ const char *metadata_checksum,
+ OstreeMutableTree **out_parent,
+ GError **error)
+{
+ gboolean ret = FALSE;
+ int i;
+ OstreeMutableTree *ret_parent = NULL;
+ OstreeMutableTree *subdir = self;
+
+ g_assert (metadata_checksum != NULL);
+
+ if (!self->metadata_checksum)
+ ostree_mutable_tree_set_metadata_checksum (self, metadata_checksum);
+
+ for (i = 0; i+1 < split_path->len; i++)
+ {
+ OstreeMutableTree *next;
+ const char *name = split_path->pdata[i];
+
+ if (g_hash_table_lookup (subdir->files, name))
+ {
+ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+ "Can't replace file with directory: %s", name);
+ goto out;
+ }
+
+ next = g_hash_table_lookup (subdir->subdirs, name);
+ if (!next)
+ {
+ next = ostree_mutable_tree_new ();
+ ostree_mutable_tree_set_metadata_checksum (next, metadata_checksum);
+ g_hash_table_insert (subdir->subdirs, g_strdup (name), next);
+ }
+
+ subdir = next;
+ }
+
+ ret_parent = g_object_ref (subdir);
+
+ ret = TRUE;
+ ot_transfer_out_value (out_parent, &ret_parent);
+ out:
+ g_clear_object (&ret_parent);
+ return ret;
+}
+
gboolean
ostree_mutable_tree_walk (OstreeMutableTree *self,
GPtrArray *split_path,
OstreeMutableTree **out_subdir,
GError **error);
+gboolean
+ostree_mutable_tree_ensure_parent_dirs (OstreeMutableTree *self,
+ GPtrArray *split_path,
+ const char *metadata_checksum,
+ OstreeMutableTree **out_parent,
+ GError **error);
+
gboolean ostree_mutable_tree_walk (OstreeMutableTree *self,
GPtrArray *split_path,
guint start,
while (g_hash_table_iter_next (&hash_iter, &key, &value))
{
const char *name = key;
+ const char *metadata_checksum;
OstreeMutableTree *child_dir = value;
char *child_dir_contents_checksum;
cancellable, error))
goto out;
+ g_assert (child_dir_contents_checksum);
g_hash_table_replace (dir_contents_checksums, g_strdup (name),
child_dir_contents_checksum); /* Transfer ownership */
+ metadata_checksum = ostree_mutable_tree_get_metadata_checksum (child_dir);
+ g_assert (metadata_checksum);
g_hash_table_replace (dir_metadata_checksums, g_strdup (name),
- g_strdup (ostree_mutable_tree_get_metadata_checksum (child_dir)));
+ g_strdup (metadata_checksum));
}
serialized_tree = create_tree_variant_from_hashes (ostree_mutable_tree_get_files (mtree),
struct archive *a,
struct archive_entry *entry,
OstreeRepoCommitModifier *modifier,
+ const char *tmp_dir_checksum,
GCancellable *cancellable,
GError **error)
{
}
else
{
- if (!ostree_mutable_tree_walk (root, split_path, 0, &parent, error))
- goto out;
+ if (tmp_dir_checksum)
+ {
+ if (!ostree_mutable_tree_ensure_parent_dirs (root, split_path,
+ tmp_dir_checksum,
+ &parent,
+ error))
+ goto out;
+ }
+ else
+ {
+ if (!ostree_mutable_tree_walk (root, split_path, 0, &parent, error))
+ goto out;
+ }
basename = (char*)split_path->pdata[split_path->len-1];
}
#endif
gboolean
-ostree_repo_stage_archive_to_mtree (OstreeRepo *self,
- GFile *archive_f,
- OstreeMutableTree *root,
- OstreeRepoCommitModifier *modifier,
- GCancellable *cancellable,
- GError **error)
+ostree_repo_stage_archive_to_mtree (OstreeRepo *self,
+ GFile *archive_f,
+ OstreeMutableTree *root,
+ OstreeRepoCommitModifier *modifier,
+ gboolean autocreate_parents,
+ GCancellable *cancellable,
+ GError **error)
{
#ifdef HAVE_LIBARCHIVE
gboolean ret = FALSE;
- struct archive *a;
+ struct archive *a = NULL;
struct archive_entry *entry;
int r;
+ GFileInfo *tmp_dir_info = NULL;
+ GChecksum *tmp_dir_checksum = NULL;
a = archive_read_new ();
archive_read_support_compression_all (a);
goto out;
}
- if (!stage_libarchive_entry_to_mtree (self, root, a, entry, modifier, cancellable, error))
+ if (autocreate_parents && !tmp_dir_checksum)
+ {
+ tmp_dir_info = g_file_info_new ();
+
+ g_file_info_set_attribute_uint32 (tmp_dir_info, "unix::uid", archive_entry_uid (entry));
+ g_file_info_set_attribute_uint32 (tmp_dir_info, "unix::gid", archive_entry_gid (entry));
+ g_file_info_set_attribute_uint32 (tmp_dir_info, "unix::mode", 0755 | S_IFDIR);
+
+ if (!stage_directory_meta (self, tmp_dir_info, NULL, &tmp_dir_checksum, cancellable, error))
+ goto out;
+ }
+
+ if (!stage_libarchive_entry_to_mtree (self, root, a,
+ entry, modifier,
+ autocreate_parents ? g_checksum_get_string (tmp_dir_checksum) : NULL,
+ cancellable, error))
goto out;
}
if (archive_read_close (a) != ARCHIVE_OK)
ret = TRUE;
out:
- (void)archive_read_close (a);
+ g_clear_object (&tmp_dir_info);
+ ot_clear_checksum (&tmp_dir_checksum);
+ if (a)
+ (void)archive_read_close (a);
return ret;
#else
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
GFile *archive,
OstreeMutableTree *tree,
OstreeRepoCommitModifier *modifier,
+ gboolean autocreate_parents,
GCancellable *cancellable,
GError **error);
static char *parent;
static char *branch;
static gboolean skip_if_unchanged;
+static gboolean tar_autocreate_parents;
static char **trees;
static gint owner_uid = -1;
static gint owner_gid = -1;
{ "tree", 0, 0, G_OPTION_ARG_STRING_ARRAY, &trees, "Overlay the given argument as a tree", "NAME" },
{ "owner-uid", 0, 0, G_OPTION_ARG_INT, &owner_uid, "Set file ownership user id", "UID" },
{ "owner-gid", 0, 0, G_OPTION_ARG_INT, &owner_gid, "Set file ownership group id", "GID" },
+ { "tar-autocreate-parents", 0, 0, G_OPTION_ARG_NONE, &tar_autocreate_parents, "When loading tar archives, automatically create parent directories as needed", NULL },
{ "skip-if-unchanged", 0, 0, G_OPTION_ARG_NONE, &skip_if_unchanged, "If the contents are unchanged from previous commit, do nothing", NULL },
{ NULL }
};
{
arg = ot_gfile_new_for_path (tree);
if (!ostree_repo_stage_archive_to_mtree (repo, arg, mtree, modifier,
+ tar_autocreate_parents,
cancellable, error))
goto out;
}
assert_file_has_content subdir/original "original"
assert_file_has_content subdir/new "new"
echo "ok tar multicommit contents"
+
+cd ${test_tmpdir}/multicommit-files
+tar -c -C files1 -z -f partial.tar.gz subdir/original
+$OSTREE commit -s 'partial' -b partial --tar-autocreate-parents --tree=tar=partial.tar.gz
+echo "ok tar partial commit"
+
+cd ${test_tmpdir}
+$OSTREE checkout partial partial-checkout
+cd partial-checkout
+assert_file_has_content subdir/original "original"